/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package pl.mwas.proteana.geneontology;

import java.util.ArrayList;
import java.util.ListIterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import pl.mwas.proteana.geneontology.util.Relation;
import pl.mwas.proteana.geneontology.util.Relationship;

/**
 *
 * @author mateusz.was
 */
public class GOTermDb {
    
    private ConcurrentHashMap<String, GOTerm> termsDb = null;

    public GOTermDb(ArrayList<GOTerm> terms) {
        termsDb = new ConcurrentHashMap<>();
        for(GOTerm term : terms) {
            termsDb.put(term.getId(), term);
        }
        validateAllTerms();
    }

    private void validateAllTerms() {
        for(Map.Entry<String, GOTerm> entry : termsDb.entrySet()) {
            GOTerm term = entry.getValue();
            GOTerm newTerm = validateTerm(term);
            termsDb.remove(term.getId());
            termsDb.put(newTerm.getId(), newTerm);
        }
    }

    public GOTerm getTerm(String id) {
        return termsDb.get(id);
    }

    private GOTerm validateTerm(GOTerm term) {
        term = initialValidation(term);
        if(term.getRelationships() != null) {
            term = validateRelations(term);
        }
        term.setValid(true);
        return term;
    }

    public int size() {
        return termsDb.size();
    }

    private GOTerm initialValidation(GOTerm term) {
        if (term.isObsolete()) {
            term.setValid(true);
        } else {
            if (term.getRelationships() != null) {
                if (term.getRelationships().isEmpty()) {
                    term.setValid(true);
                } else {
                    term.setValid(false);
                }
            } else {
                term.setValid(true);
            }
        }
        return term;
    }
        
    private GOTerm validateRelations(GOTerm term) {
        ArrayList<Relation> relations = term.getRelationships();
        for (ListIterator<Relation> it = relations.listIterator(); it.hasNext();) {
            Relation rel = it.next();
            GOTerm mockTerm = rel.getRelatedTerm();
            Relationship mockRelationType = rel.getType();
            GOTerm realTerm = termsDb.get(mockTerm.getId());
            if(realTerm.isValid()) {
                it.remove();
                it.add(new Relation(mockRelationType, realTerm));
            }
            else {
                it.remove();
                it.add(new Relation(mockRelationType, realTerm));
                validateTerm(realTerm);
            }
        }
        return term;
    }

    public ConcurrentHashMap<String, GOTerm> getTermsDb() {
        return termsDb;
    }
    
}
